﻿namespace Voxel2Unity
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using UnityEngine;

    public static class VoxFile
    {
        public static byte[] GetMainByte(VoxData _voxData)
        {
            List<byte> list = new List<byte>();
            list.AddRange(Encoding.Default.GetBytes("VOX "));
            list.AddRange(_voxData.Version);
            list.AddRange(Encoding.Default.GetBytes("MAIN"));
            list.AddRange(BitConverter.GetBytes(0));
            byte[] voxByte = GetVoxByte(_voxData, _voxData.Palatte);
            list.AddRange(BitConverter.GetBytes(voxByte.Length));
            list.AddRange(voxByte);
            byte[] array = new byte[list.Count];
            list.CopyTo(array);
            return array;
        }

        public static byte[] GetVoxByte(VoxData _data, Color[] _palatte)
        {
            List<byte> list = new List<byte>();
            list.AddRange(Encoding.Default.GetBytes("SIZE"));
            list.AddRange(BitConverter.GetBytes(12));
            list.AddRange(BitConverter.GetBytes(0));
            list.AddRange(BitConverter.GetBytes(_data.SizeX));
            list.AddRange(BitConverter.GetBytes(_data.SizeY));
            list.AddRange(BitConverter.GetBytes(_data.SizeZ));
            list.AddRange(Encoding.Default.GetBytes("XYZI"));
            list.AddRange(BitConverter.GetBytes((int) ((_data.VoxelNum * 4) + 4)));
            list.AddRange(BitConverter.GetBytes(0));
            list.AddRange(BitConverter.GetBytes(_data.VoxelNum));
            for (int i = 0; i < _data.SizeX; i++)
            {
                for (int k = 0; k < _data.SizeY; k++)
                {
                    for (int m = 0; m < _data.SizeZ; m++)
                    {
                        if (_data.Voxels[i, k, m] != 0)
                        {
                            list.Add((byte) i);
                            list.Add((byte) k);
                            list.Add((byte) m);
                            list.Add((byte) _data.Voxels[i, k, m]);
                        }
                    }
                }
            }
            list.AddRange(Encoding.Default.GetBytes("RGBA"));
            list.AddRange(BitConverter.GetBytes(0x400));
            list.AddRange(BitConverter.GetBytes(0));
            for (int j = 0; j < 0x100; j++)
            {
                Color color = (j >= _palatte.Length) ? new Color() : _palatte[j];
                list.Add((byte) (color.r * 255f));
                list.Add((byte) (color.g * 255f));
                list.Add((byte) (color.b * 255f));
                list.Add((byte) (color.a * 255f));
            }
            byte[] array = new byte[list.Count];
            list.CopyTo(array);
            return array;
        }

        public static VoxData LoadVoxel(string path)
        {
            return LoadVoxel(Util.FileToByte(path));
        }

        public static VoxData LoadVoxel(byte[] _data)
        {
            if (((_data[0] != 0x56) || (_data[1] != 0x4f)) || ((_data[2] != 0x58) || (_data[3] != 0x20)))
            {
                Debug.LogError("Error Magic Number");
                return null;
            }
            using (MemoryStream stream = new MemoryStream(_data))
            {
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    VoxData data = new VoxData();
                    reader.ReadInt32();
                    data.Version = reader.ReadBytes(4);
                    byte[] buffer = reader.ReadBytes(4);
                    if (((buffer[0] != 0x4d) || (buffer[1] != 0x41)) || ((buffer[2] != 0x49) || (buffer[3] != 0x4e)))
                    {
                        Debug.LogError("Error main ID");
                        return null;
                    }
                    int count = reader.ReadInt32();
                    int num2 = reader.ReadInt32();
                    reader.ReadBytes(count);
                    int num3 = 0;
                    while (num3 < num2)
                    {
                        buffer = reader.ReadBytes(4);
                        if (((buffer[0] == 0x53) && (buffer[1] == 0x49)) && ((buffer[2] == 90) && (buffer[3] == 0x45)))
                        {
                            num3 += ReadSizeChunk(reader, data);
                        }
                        else
                        {
                            if (((buffer[0] == 0x58) && (buffer[1] == 0x59)) && ((buffer[2] == 90) && (buffer[3] == 0x49)))
                            {
                                num3 += ReadVoxelChunk(reader, data);
                                continue;
                            }
                            if (((buffer[0] == 0x52) && (buffer[1] == 0x47)) && ((buffer[2] == 0x42) && (buffer[3] == 0x41)))
                            {
                                data.Palatte = new Color[0x100];
                                num3 += ReadPalattee(reader, data.Palatte);
                                continue;
                            }
                            int num4 = reader.ReadInt32();
                            int num5 = reader.ReadInt32();
                            reader.ReadBytes(num4 + num5);
                            num3 += (((num4 + num5) + 4) + 4) + 4;
                        }
                    }
                    if (data.Palatte == null)
                    {
                        data.Palatte = DefaultPallete;
                    }
                    return data;
                }
            }
        }

        private static int ReadPalattee(BinaryReader _br, Color[] _colors)
        {
            int num = _br.ReadInt32();
            int count = _br.ReadInt32();
            for (int i = 0; i < 0x100; i++)
            {
                _colors[i] = new Color(((float) _br.ReadByte()) / 255f, ((float) _br.ReadByte()) / 255f, ((float) _br.ReadByte()) / 255f, ((float) _br.ReadByte()) / 255f);
            }
            if (count > 0)
            {
                _br.ReadBytes(count);
            }
            return ((num + count) + 12);
        }

        private static int ReadSizeChunk(BinaryReader _br, VoxData _mainData)
        {
            int num = _br.ReadInt32();
            int count = _br.ReadInt32();
            _mainData.SizeX = _br.ReadInt32();
            _mainData.SizeY = _br.ReadInt32();
            _mainData.SizeZ = _br.ReadInt32();
            _mainData.Voxels = new int[_mainData.SizeX, _mainData.SizeY, _mainData.SizeZ];
            if (count > 0)
            {
                _br.ReadBytes(count);
            }
            return ((num + count) + 12);
        }

        private static int ReadVoxelChunk(BinaryReader _br, VoxData _mainData)
        {
            int num = _br.ReadInt32();
            int count = _br.ReadInt32();
            int num3 = _br.ReadInt32();
            for (int i = 0; i < num3; i++)
            {
                int num5 = _br.ReadByte();
                int num6 = _br.ReadByte();
                int num7 = _br.ReadByte();
                _mainData.Voxels[num5, num6, num7] = _br.ReadByte();
            }
            if (count > 0)
            {
                _br.ReadBytes(count);
            }
            return ((num + count) + 12);
        }

        private static Color[] DefaultPallete
        {
            get
            {
                Color[] colorArray = new Color[0x100];
                int index = 0;
                for (int i = 10; i >= 0; i -= 2)
                {
                    for (int num3 = 10; num3 >= 0; num3 -= 2)
                    {
                        for (int num4 = 10; num4 >= 0; num4 -= 2)
                        {
                            if (((i + num3) + num4) != 0)
                            {
                                colorArray[index] = new Color(((float) i) / 10f, ((float) num3) / 10f, ((float) num4) / 10f);
                                index++;
                            }
                        }
                    }
                }
                for (int j = 14; j > 0; j--)
                {
                    if ((j % 3) != 0)
                    {
                        colorArray[index] = new Color(((float) j) / 15f, 0f, 0f);
                        index++;
                    }
                }
                for (int k = 14; k > 0; k--)
                {
                    if ((k % 3) != 0)
                    {
                        colorArray[index] = new Color(0f, ((float) k) / 15f, 0f);
                        index++;
                    }
                }
                for (int m = 14; m > 0; m--)
                {
                    if ((m % 3) != 0)
                    {
                        colorArray[index] = new Color(0f, 0f, ((float) m) / 15f);
                        index++;
                    }
                }
                for (int n = 14; n > 0; n--)
                {
                    if ((n % 3) != 0)
                    {
                        colorArray[index] = new Color(((float) n) / 15f, ((float) n) / 15f, ((float) n) / 15f);
                        index++;
                    }
                }
                colorArray[0xff] = new Color(0f, 0f, 0f, 1f);
                return colorArray;
            }
        }
    }
}

